#include "somfy_Curtain_Ctrl_Driver.h"

#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "usb_hotplug_check.h"
#include "env_ctrol_service.h"

/*存储状态的参数及状态信息*/
STRUCT_SOMFY_CURTAIN_INFO StruSomfyCurtainInfo = {0x00};
STRUCT_SOMFY_CURTAIN_CONTROL_CMDLINE struSomfyCurtainControl = {0x00};

/*尚飞窗帘控制的起始码 : 每种窗帘对应的起始码可能不同*/
uint8_t SomfyCurtainControlStartCode[8][16] = {SOMFY_CURTAIN_CONTROL_START_CODE};

/*外部接口定义*/

void somfy_curtain_control_init(uint8_t channel ,uint32_t bautrate,uint8_t initstate)
{

	uint8_t i = 0x00;
	SOMFY_CURTAIN_LOG("somfy curtain control init ");

	memset(StruSomfyCurtainInfo.curtaininfo,0,sizeof(StruSomfyCurtainInfo.curtaininfo));
	memset(&struSomfyCurtainControl,0,sizeof (struSomfyCurtainControl));

	/*默认的窗帘控制起始码*/
	StruSomfyCurtainInfo.startcodeindex = 0x00;
	
	StruSomfyCurtainInfo.serialbautrate = bautrate;
	StruSomfyCurtainInfo.channelid = channel;
	StruSomfyCurtainInfo.serialinitok = initstate;

	return ;
}

/**
*将要发送的数据进行打包 :
*参数 deviceid :设备地址 
	  funcode :功能码
	  srcdata: 要发送的数据长度
	  srcdatalen ：要发送的数据
	  destdata : 打包之后要发送的的数据
*返回值 : 打包之后 要发送的数据帧长度
*
*/
uint8_t somfy_curtain_control_pack_data(uint32_t deviceid,uint16_t funcode,uint8_t dataadd,uint8_t srcdatalen,int32_t *pdata,uint8_t * destdata)
{

	uint8_t i = 0x00;
	
	uint8_t cnt = 0x00;
	uint16_t tmpcrc = 0x00;

	
	/*获取以下参数 */
	/* 起始码 :*/
	for (i = 0x00;i < SOMFY_CURTAIN_CONTROL_START_CODE_LENGTH;i ++)
	{
		destdata[cnt++] = SomfyCurtainControlStartCode[StruSomfyCurtainInfo.startcodeindex][i];
	}

	/*设备地址 : 3个字节:先发送地址高8位 在发送地址低8位*/
	destdata[cnt++] = (deviceid >>16)& 0xff;
	destdata[cnt++] = (deviceid >>8) & 0xff;
	destdata[cnt++] = (deviceid >>0) & 0xff;

	/*功能码  : 2个字节*/
	destdata[cnt++] = (funcode >> 8)& 0xff;
	destdata[cnt++] = (funcode >> 0) & 0xff;

	/*校验位  : 2个字节  校验*/
	tmpcrc = get_crc(deviceid);
	cnt += 2;	

	/*crc value*/
	destdata[cnt - 2] = (tmpcrc >> 8) & 0xff;	
	destdata[cnt - 1] = (tmpcrc) & 0xff ;

	return cnt;
	
}


/********************************************************************************
*函数: somfy_curtain_control_unpack_data
*说明：解析接收到的数据
*参数 
*	  pdata :接收到的数据
*	  len：接收到的数据长度
*	  deviceid :设备地址 
*	  funcode :功能码
*	  dataadd :已发送数据的起始数据地址
*	  num :发送的数据长度
*返回值 : 接收到的数据长度 ，接收成功为>0 ,接收失败为0
*
*********************************************************************************/
uint8_t somfy_curtain_control_unpack_data(uint8_t *pdata,uint8_t len,uint32_t devid,uint16_t func,uint8_t dataadd,uint8_t num)
{

	uint8_t  i 		= 0x00;
	uint8_t  cnt 	= 0x00;

	uint8_t  nbyte 	= 0x00;

	uint16_t tmpcrc = 0x00;
	uint16_t calcrc = 0x00;


	int tmp = 0x00;
	uint8_t tmpstartcode[SOMFY_CURTAIN_CONTROL_START_CODE_LENGTH] = SOMFY_CURTAIN_CONTROL_START_CODE;

	SOMFY_CURTAIN_LOG("entry somfy curtain unpack data!");

	/*接收帧长度大于最小帧长度*/
	if (len < SOMFY_CURTAIN_CONTROL_RECV_FRAME_MINI_LENGTH)
	{
		SOMFY_CURTAIN_LOG("somfy curtain frame receive not complete!");
		return 0;
	}

	/*起始码 */
	for(i = 0x00;i < SOMFY_CURTAIN_CONTROL_START_CODE_LENGTH;i ++)
	{
		if (pdata[cnt ++] != tmpstartcode[i])
		{
			SOMFY_CURTAIN_LOG("somfy curtain start code receive err!");
			return 0x00;
		}
	}

	
	/*发送帧的设备地址 :作为一帧数据发送之后的等待接收帧标记记录*/
	if (devid != (pdata[cnt + 2] |(pdata[cnt + 1] << 8) | (pdata[cnt] << 16)))
	{
		SOMFY_CURTAIN_LOG("somfy curtain devid receive err!");	
		return 0;
	}
	cnt += 3;
	
	/*crc校验*/
	tmpcrc = pdata[len - 1 ] | (pdata[len - 2 ] << 8);
	calcrc = get_crc(devid);

	if (calcrc != tmpcrc)
	{	
		SOMFY_CURTAIN_LOG("somfy curtain crc receive err!");
		return 0;
	}

	if (func !=(pdata[cnt + 1] | (pdata[cnt] << 8)))
	{	
		SOMFY_CURTAIN_LOG("somfy curtain funcode receive err!");
		return 0;
	}

	StruSomfyCurtainInfo.devid = devid;

	SOMFY_CURTAIN_LOG("somfy curtain control data receive ok!");

	cnt = len;
	return (cnt);
	
}


/********************************************************************************
*函数 ：curtain_control_read_data
*说明：将接收的数据传递到上层
*参数 
*	  pdata :接收到的数据
*	  len：接收到的数据长度
*	  deviceid :设备地址 
*	  funcode :功能码
*	  dataadd :已发送数据的起始数据地址
*	  num :发送的数据长度
*返回值 : 接收到的数据长度 ，接收成功为>0 ,接收失败为0
*
*********************************************************************************/
uint8_t somfy_curtain_control_read_data(uint32_t deviceid,uint16_t funcode,uint8_t dataadd,uint8_t srcdatalen,uint8_t * destdata)
{
	return 0x00;
}

/***********************************************************
*
*函数名:
*
*作用：设备控制通道
*
*	
*
*返回值 :0x00
************************************************************/
uint8_t somfy_curtain_get_cmd_channel(uint8_t * channel)
{

	uint8_t ret = 0x00;
	if (StruSomfyCurtainInfo.serialinitok != USB_SERIAL_DEVICE_INIT_OK)
	{
		ret = 0x01;
	}
	else
	{
		if (StruSomfyCurtainInfo.channelid > USB_SERIAL_AMOUNT)
		{
			ret = 0x01;
		}
		else
		{
			*channel = StruSomfyCurtainInfo.channelid ;
		}
	}

	return ret ;
}


/////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////
//--------------------------------------------------------------
// 函数名称: Get_CRC16_byGID
// 功能描述: 得到CRC16
// 输入参数: 待进行CRC校验计算的报文 待校验的报文长度
// 返回参数: CRC16
// 修改记录:
// 2015-01-11, PiaoHong 创建函数
//---------------------------------------------------------------
uint16_t get_crc (uint32_t data)
{

	uint8_t tmp[4] = {0x00};
	uint16_t crc16 = 0xFFFF;

	/* 地址从低到高*/
	tmp[0] =  data & 0x000000ff;
	tmp[1] = (data >> 8)  & 0x000000ff;
	tmp[2] = (data >> 16) & 0x000000ff;
	tmp[3] = (data >> 24) & 0x000000ff;

	tmp[0] =  ~tmp[0];
	tmp[0] &= 0x000000ff;

	tmp[1] =  ~tmp[1];
	tmp[1] &= 0x000000ff;

	tmp[2] =  ~tmp[2];
	tmp[2] &= 0x000000ff;

	crc16 = SOMFY_CURTAIN_CHECK_SUM - tmp[0] - tmp[1] - tmp[2];
	return crc16;

}


